using System;
using System.Collections.Generic;
using System.Text;
using Spacedash.Game.Nodes;
using Barrage.Global;
using SlimDX;
using Barrage.Elements;

namespace Spacedash.Game.Cameras
{
    class PursuitCamera:Camera
    {
        ShipNode target;
        Random random;
        Vector3 position;
        Vector3 previousTilt;
        const float MAX_TILT = 0.3f;

        public override Vector3 Position
        {
            get { return position; }
        }

        Vector2 viewportSize;
        const float MIN_FOV = (float)System.Math.PI / 4;
        const float MAX_FOV = (float)Math.PI / 2;
        float fov = MIN_FOV;

        void UpdateProjection()
        {
            projection = Matrix.PerspectiveFovLH(fov, viewportSize.X / (float)viewportSize.Y, 0.1f, 5000);
        }

        public PursuitCamera(ShipNode target,Vector2 viewportSize)
        {
            this.viewportSize = viewportSize;
            random = new Random();
            UpdateProjection();
            this.target = target;
            motion.Matrix = Matrix.LookAtLH(target.Motion.Translation + new Vector3(0, 10, 10), target.Motion.Translation, Vector3.UnitY);
        }

        protected override void DoUpdate()
        {
            float baseYHeight = 12;
            float baseZOffset = -16;
            float targetZOffset = 36;

            Vector3 cameraTarget = target.Ship.Motion.Translation;
            Vector3 offset1 = new Vector3(0, target.Ship.Normal.Y * baseYHeight - target.Ship.Normal.Z * baseZOffset, target.Ship.Normal.Y * baseZOffset + target.Ship.Normal.Z * baseYHeight);
            Vector3 offset2 = new Vector3(0, -target.Ship.Normal.Z * targetZOffset, target.Ship.Normal.Y * targetZOffset);

            // Random vibration on high speeds
            float tiltAmount = (float)Math.Pow(Math.Max(0, Math.Min(10,target.Ship.Speed - 3)), 1.35f) / 125.0f;
            if (tiltAmount > 0)
            {
                Vector3 tiltVector = new Vector3(((float)random.NextDouble() - 0.5f) * tiltAmount, ((float)random.NextDouble() - 0.5f) * tiltAmount, ((float)random.NextDouble() - 0.5f) * tiltAmount);
                previousTilt = Vector3.Clamp(GameMath.Damping(previousTilt, tiltVector, 0.0001f, Timer.DefaultTimer.LastIntervalSeconds), new Vector3(-MAX_TILT, -MAX_TILT, -MAX_TILT), new Vector3(MAX_TILT, MAX_TILT, MAX_TILT));
                offset1 += previousTilt;
                offset2 += previousTilt*targetZOffset;
            }
            position = (cameraTarget + offset1);//GameMath.Damping(position,(cameraTarget+offset1),new Vector3(0.1f,0.001f,0.001f),Timer.DefaultTimer.LastIntervalSeconds);
            //position = cameraTarget + offset1;
            motion.Matrix = Matrix.LookAtLH(position, cameraTarget + offset2, new Vector3(0, target.Ship.Normal.Y, target.Ship.Normal.Z));

            fov = GameMath.Damping(fov, MIN_FOV + target.Ship.Speed / 15.0f, 0.25f, Timer.DefaultTimer.LastIntervalSeconds);
            fov = Math.Min(fov, MAX_FOV);
            UpdateProjection();
            //motion.Matrix = Matrix.LookAtLH(cameraTarget + new Vector3(11, 0, 0), cameraTarget + new Vector3(0, 0, 0), Vector3.UnitY);
            base.DoUpdate();
        }
    }
}
